package com.kx.yooli.kx.wechat.utils.uuid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.security.SecureRandom;

/**
 * @author john_sqwen-childe.wen
 * date 2024/4/8
 * PROJECT_NAME wechat
 * description create UUIDGenerator by john_sqwen
 * and  value is
 */
public class UUIDGenerator {
    private final Logger log = LoggerFactory.getLogger(UUIDGenerator.class);
    private static SecureRandom seederStatic = null;
    private static byte[] addr = null;
    private static String midValueStatic = null;
    private String midValue = null;
    private SecureRandom seeder = null;
    private static long prevMillis = 0L;
    private static byte[] addrBytes = null;

    static
    {
        try
        {
            addr = InetAddress.getLocalHost().getAddress();
            addrBytes = InetAddress.getLocalHost().getAddress();
            StringBuffer buffer = new StringBuffer(8);
            buffer.append(toHex(toInt(addr), 8));
            midValueStatic = buffer.toString();
            seederStatic = new SecureRandom();
            seederStatic.nextInt();
        }
        catch (Exception localException)
        {
        }
    }

    public UUIDGenerator()
    {
        StringBuffer buffer = new StringBuffer(16);
        buffer.append(midValueStatic);
        buffer.append(toHex(System.identityHashCode(this), 8));
        this.midValue = buffer.toString();
        this.seeder = new SecureRandom();
        this.seeder.nextInt();
    }

    public static String generate(Object obj) {
        StringBuffer uid = new StringBuffer(32);

        long currentTimeMillis = System.currentTimeMillis();
        uid.append(toHex((int)(currentTimeMillis & 0xFFFFFFFF), 8));

        uid.append(midValueStatic);

        uid.append(toHex(System.identityHashCode(obj), 8));

        uid.append(toHex(getRandom(), 8));

        return uid.toString();
    }

    public String generate() {
        StringBuffer uid = new StringBuffer(32);

        long currentTimeMillis = System.currentTimeMillis();
        uid.append(toHex((int)(currentTimeMillis & 0xFFFFFFFF), 8));

        uid.append(this.midValue);

        uid.append(toHex(this.seeder.nextInt(), 8));

        return uid.toString();
    }

    private static String toHex(int value, int length) {
        char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'A', 'B', 'C', 'D', 'E', 'F' };
        StringBuffer buffer = new StringBuffer(length);
        int shift = length - 1 << 2;
        for (int i = -1; ++i < length; ) {
            buffer.append(hexDigits[(value >> shift & 0xF)]);
            value <<= 4;
        }

        return buffer.toString();
    }

    private static int toInt(byte[] bytes) {
        int value = 0;
        for (int i = -1; ++i < bytes.length; ) {
            value <<= 8;
            value |= bytes[i];
        }

        return value;
    }

    private static synchronized int getRandom() {
        return seederStatic.nextInt();
    }

    private static synchronized long getSystemTimeMillis() {
        long millis = System.currentTimeMillis();
        if (millis > prevMillis)
            prevMillis = millis;
        else {
            prevMillis += 1L;
        }
        return prevMillis;
    }

    public static Long getUniqueLong() {
        long l = getSystemTimeMillis();

        l *= 1000L;
        long b1 = addrBytes[3] & 0xFF;
        l += b1;
        return l;
    }
}
